.\" Copyright (c) 2005-2020 Julien Nadeau Carriere <vedge@csoft.net>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 30, 2005
.Dt AG_MENU 3
.Os
.ds vT Agar API Reference
.ds oS Agar 1.0
.Sh NAME
.Nm AG_Menu
.Nd agar menu system
.Sh SYNOPSIS
.Bd -literal
#include <agar/core.h>
#include <agar/gui.h>
.Ed
.Sh DESCRIPTION
.\" IMAGE(http://libagar.org/widgets/AG_Menu.png, "An expanded AG_Menu")
The
.Nm
widget displays a hierarchical menu composed of items of the following types:
.Bl -tag -width "Dynamic items "
.It Action items
Selecting the item causes a specified function to be invoked, with the
specified arguments.
See
.Fn AG_MenuAction .
.It Boolean items
A menu item tied to a variable describing a boolean value (either an integer,
or specific bits in an integer).
Selecting an active boolean item will toggle the value.
See
.Fn AG_MenuBool .
.It Separators
A cosmetic separator, displayed as a horizontal or vertical bar depending
on the display mode.
See
.Fn AG_MenuSeparator .
.It Dynamic items
A dynamically updated menu item.
The item itself (possibly including child items) are expected to be generated
by a specified callback routine.
The first argument to the callback routine is a pointer to the
.Ft AG_MenuItem .
An example of a dynamic item would be a submenu displaying the current
contents of a folder.
See
.Fn AG_MenuDynamicItem .
.El
.Pp
Menu elements can be displayed in text format with the
.Ft AG_MenuView
widget, or in icon format using
.Xr AG_Toolbar 3 .
.Pp
Note: Many functions of
.Nm
accept
.Fa fn
and
.Fa fnArgs
arguments; see
.Xr AG_Event 3
for details on event handler functions in Agar.
.Sh INHERITANCE HIERARCHY
.Xr AG_Object 3 ->
.Xr AG_Widget 3 ->
.Nm .
.Sh INITIALIZATION
.nr nS 1
.Ft "AG_Menu *"
.Fn AG_MenuNew "AG_Widget *parent" "Uint flags"
.Pp
.Ft "AG_Menu *"
.Fn AG_MenuNewGlobal "Uint flags"
.Pp
.Ft void
.Fn AG_MenuExpand "AG_Widget *parentWidget" "AG_MenuItem *item" "int x" "int y"
.Pp
.Ft void
.Fn AG_MenuCollapse "AG_MenuItem *item"
.Pp
.Ft void
.Fn AG_MenuCollapseAll "AG_Menu *m"
.Pp
.Ft void
.Fn AG_MenuSetPadding "AG_Menu *menu" "int left" "int right" "int top" "int bottom"
.Pp
.Ft void
.Fn AG_MenuSetLabelPadding "AG_Menu *menu" "int left" "int right" "int top" "int bottom"
.Pp
.nr nS 0
The
.Fn AG_MenuNew
function allocates, initializes, and attaches a new
.Nm
widget.
Acceptable
.Fa flags
include:
.Bl -tag -width "AG_MENU_EXPAND "
.It AG_MENU_HFILL
Expand horizontally in parent container.
.It AG_MENU_VFILL
Expand vertically in parent container.
.It AG_MENU_EXPAND
Shorthand for
.Dv AG_MENU_HFILL | AG_MENU_VFILL .
.El
.Pp
The
.Fn AG_MenuNewGlobal
constructor creates a global "application menu".
The manner in which application menus are displayed is dependent on the
underlying platform and graphics system.
If there is insufficient memory, or an application menu is already defined,
.Fn AG_MenuNewGlobal
may fail returning NULL.
.Pp
The
.Fn AG_MenuExpand
function creates a new window containing an
.Ft AG_MenuView
widget displaying the menu items under
.Fa item .
The optional
.Fa parentWidget
argument should point to some parent widget or window.
The new window is created at coordinates
.Fa x ,
.Fa y
relative to
.Fa parentWidget .
The newly created window is also attached to the parent window of
.Fa parentWidget .
.Pp
.Fn AG_MenuCollapse
closes the window previously created by
.Fn AG_MenuExpand
for the given menu item.
.Fn AG_MenuCollapseAll
closes all windows generated by
.Fn AG_MenuExpand
for the whole menu
.Fa m .
.Pp
.Fn AG_MenuSetPadding
sets the global padding around all menu items, in pixels.
.Fn AG_MenuSetLabelPadding
sets the padding around the text label of items.
If a parameter is -1, its current value is preserved.
.Sh MENU ITEMS
.nr nS 1
.Ft "AG_MenuItem *"
.Fn AG_MenuNode "AG_MenuItem *parent" "const char *text" "const AG_Surface *icon"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuAction "AG_MenuItem *parent" "const char *text" "const AG_Surface *icon" "void (*fn)(AG_Event *)" "const char *fnArgs" "..."
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuActionKb "AG_MenuItem *parent" "const char *text" "const AG_Surface *icon" "AG_KeySym keysym" "AG_KeyMod keymod" "void (*fn)(AG_Event *)" "const char *fnArgs" "..."
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuDynamicItem "AG_MenuItem *parent" "const char *text" "const AG_Surface *icon" "void (*fn)(AG_Event *)" "const char *fnArgs" "..."
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuDynamicItemKb "AG_MenuItem *parent" "const char *text" "const AG_Surface *icon" "AG_KeySym key" "AG_KeyMod kmod" "void (*fn)(AG_Event *)" "const char *fnArgs" "..."
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuTool "AG_MenuItem *parent" "AG_Toolbar *toolbar" "const char *text" "const AG_Surface *icon" "AG_KeySym keysym" "AG_KeyMod keymod" "void (*fn)(AG_Event *)" "const char *fnArgs" "..."
.Pp
.Ft "void"
.Fn AG_MenuSetIcon "AG_MenuItem *item" "const AG_Surface *su"
.Pp
.Ft "void"
.Fn AG_MenuSetLabel "AG_MenuItem *item" "const char *format" "..."
.Pp
.Ft "void"
.Fn AG_MenuSetLabelS "AG_MenuItem *item" "const char *label"
.Pp
.Ft "void"
.Fn AG_MenuSetPollFn "AG_MenuItem *item" "void (*fn)(AG_Event *)" "const char *fnArgs" "..."
.Pp
.Ft "void"
.Fn AG_MenuDel "AG_MenuItem *menu"
.Pp
.Ft "void"
.Fn AG_MenuState "AG_MenuItem *item" "int state"
.Pp
.Ft "void"
.Fn AG_MenuEnable "AG_MenuItem *item"
.Pp
.Ft "void"
.Fn AG_MenuDisable "AG_MenuItem *item"
.Pp
.nr nS 0
The
.Fn AG_MenuNode
function inserts a new node (no-op) item displaying the given
.Fa text
and
.Fa icon
(or NULL if none).
Node items are typically only used to attach subitems.
.Pp
The
.Fn AG_MenuAction
function inserts a new action item displaying the given
.Fa text
and
.Fa icon
(or NULL if none).
When selected, the item will invoke the specified event handler function
.Fa fn .
.Pp
The
.Fn AG_MenuActionKb
variant also associates the action with the given
.Xr AG_KeySym 3
and modifier.
.Pp
The
.Fn AG_MenuTool
variant also inserts an item into the specified
.Xr AG_Toolbar 3
widget.
.Pp
The
.Fn AG_MenuSetIcon
function sets the icon associated with a menu item.
If an argument of NULL is given, any existing icon is removed.
.Pp
.Fn AG_MenuSetLabel
changes the text associated with an existing menu item.
.Fn AG_MenuSetPollFn
changes the callback function associated with a given item (previously
created with
.Fn AG_MenuDynamicItem ) .
.Pp
The
.Fn AG_MenuDynamicItem
function creates a dynamic menu item.
The specified callback routine
.Fa fn
will be invoked repeatedly to update the menu item, with the
.Nm
as receiver object (access with
.Fn AG_MENU_SELF ) ,
and the first Pointer argument a pointer to the
.Ft AG_MenuItem .
The callback routine is allowed to directly modify the
.Va state
member of the
.Ft AG_MenuItem .
This variable defines the boolean state for the specified menu item
(0 = disabled, 1 = enabled).
If
.Va state
is -1, the boolean state is determined from any boolean/flag binding
associated with the item.
The callback can also change the text label and icon using
.Fn AG_MenuSetLabel
and
.Fn AG_MenuSetIcon .
.Pp
The
.Fn AG_MenuDel
routine deletes the specified menu item and its sub-items.
.Pp
The
.Fn AG_MenuState
(or its variants
.Fn AG_MenuEnable
and
.Fn AG_MenuDisable )
request that all subsequently created menu items are assigned the given
state.
.Sh BOOLEAN AND BITMASK ITEMS
.nr nS 1
.Ft "AG_MenuItem *"
.Fn AG_MenuBool "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "int *value" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuBoolMp "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "int *value" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntBool "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "int *value" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntBoolMp "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "int *value" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt8Bool "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "Uint8 *value" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt8BoolMp "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "Uint8 *value" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuFlags "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "int *value" "int flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuFlagsMp "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "int *value" "int flags" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntFlags "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "int *value" "int flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntFlagsMp "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "int *value" "int flags" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt8Flags "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "Uint8 *value" "Uint8 flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt8FlagsMp "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "Uint8 *value" "Uint8 flags" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt16Flags "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "Uint16 *value" "Uint16 flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt16FlagsMp "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "Uint16 *value" "Uint16 flags" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt32Flags "AG_MenuItem *" "const char *text" "const AG_Surface *icon" "Uint32 *value" "Uint32 flags" "int invert"
.Pp
.nr nS 0
The
.Fn AG_Menu*Bool
functions create a new item that binds to the given boolean variable.
If the
.Fa invert
parameter is non-zero, the actual value is inverted.
.Pp
The
.Fn AG_Menu*Flags
functions create a new item controlling one or more bits inside an integer
value.
The
.Fa flags
argument specifies the bitmask.
If
.Fa invert
is non-zero, the bits are inverted.
.Pp
The
.Fn AG_Menu*BoolMp
and
.Fn AG_Menu*FlagsMp
variants accept a
.Ft "AG_Mutex *"
argument specifying a mutex to acquire prior to reading or writing the data.
.Sh OTHER ITEMS
.nr nS 1
.Ft "void"
.Fn AG_MenuSeparator "AG_MenuItem *item"
.Pp
.Ft "void"
.Fn AG_MenuSection "AG_MenuItem *item" "const char *format" "..."
.Pp
.Ft "void"
.Fn AG_MenuSectionS "AG_MenuItem *item" "const char *text"
.Pp
.nr nS 0
The
.Fn AG_MenuSeparator
function inserts a horizontal menu separator.
.Pp
.Fn AG_MenuSection
creates a non-selectable item displaying the given text.
.Sh POPUP MENUS
.nr nS 1
.Ft "AG_PopupMenu *"
.Fn AG_PopupNew "AG_Widget *widget"
.Pp
.Ft void
.Fn AG_PopupShow "AG_PopupMenu *pm"
.Pp
.Ft void
.Fn AG_PopupShowAt "AG_PopupMenu *pm" "int x" "int y"
.Pp
.Ft void
.Fn AG_PopupHide "AG_PopupMenu *pm"
.Pp
.Ft void
.Fn AG_PopupDestroy "AG_Widget *widget" "AG_PopupMenu *pm"
.Pp
.nr nS 0
The
.Fn AG_PopupNew
function creates a new popup menu and associates it with the specified widget.
This association will cause the popup menu to be automatically freed when the
given widget is destroyed.
.Pp
Once a popup menu is created, new items can be inserted using the
.Va root
member of the
.Ft AG_PopupMenu
structure as parent.
.Pp
.Fn AG_PopupShow
displays the popup menu at the current mouse coordinates.
.Fn AG_PopupShowAt
accepts global (view) coordinates.
.Fn AG_PopupHide
hides the popup menu from the user.
.Pp
.Fn AG_PopupDestroy
detaches the specified popup menu from its associated widget, and releases
its allocated resources.
This function is automatically invoked whenever a widget is destroyed.
.Sh EVENTS
The
.Nm
widget does not generate any event.
.Sh BINDINGS
The
.Nm
widget does not provide any binding.
.Sh STRUCTURE DATA
For the
.Ft AG_Menu
object:
.Bl -tag -width "AG_MenuItem *itemSel "
.It Ft AG_MenuItem *root
The root menu item (read-only).
.It Ft AG_MenuItem *itemSel
The currently selected top-level item (read-only).
Top-level items are attached directly to
.Va root .
.It Ft int selecting
Selection is in progress if set to 1 (read-only).
.El
.Pp
For the
.Ft AG_MenuItem
structure:
.Bl -tag -width "int (*stateFn)(AG_Event *)"
.It Ft char *text
Displayed text for the menu item (read-only, set by
.Fn AG_MenuSetLabel ) .
.It Ft AG_Surface *iconSrc
The
.Xr AG_Surface 3
of the menu icon, or NULL (read-only, set by
.Fn AG_MenuSetIcon ) .
.It Ft int value
The boolean state of the item, used by default.
If the boolean state was bound to another variable (e.g., using
.Fn AG_MenuBool )
then this value will be ignored.
.It Ft int state
Make item clickable (1) or disabled (0).
.It Ft int (*stateFn)(AG_Event *)
Evaluate function to determine if item is active.
Overrides the
.Va state
flag.
.It Ft AG_Menu *pmenu
Back pointer to the parent
.Ft AG_Menu
(read-only).
.El
.Sh EXAMPLES
The following code fragment creates a popup menu with a disabled item:
.Bd -literal -offset indent
AG_PopupMenu *pm;
AG_MenuItem *mi;

pm = AG_PopupNew(myParentWidget);
AG_MenuAction(pm->root, "Copy", NULL, DoCopy, NULL);
mi = AG_MenuAction(pm->root, "Paste", NULL, DoPaste, NULL);
mi->state = (myClipboard->contents > 0);
.Ed
.Pp
The following code fragment creates a popup menu with a dynamically
determined "disabled" state:
.Bd -literal -offset indent
static int
PasteActive(AG_Event *event)
{
	Clipboard *C = AG_PTR(1);
	return (C->contents > 0);
}

AG_PopupMenu *pm;
AG_MenuItem *mi;

pm = AG_PopupNew(myParentWidget);
AG_MenuAction(pm->root, "Copy", NULL, DoCopy, NULL);
mi = AG_MenuAction(pm->root, "Paste", NULL, DoPaste, NULL);
mi->stateFn = AG_SetIntFn(pm->menu, NULL, PasteActive, "%p", myClipboard);
.Ed
.Pp
The following code fragment associates a menu with an
.Xr AG_Toolbar 3 .
Buttons and menu entries are created for the same actions.
.Bd -literal -offset indent
AG_Toolbar *toolbar;
AG_Menu *menu;
AG_MenuItem *item;

toolbar = AG_ToolbarNew(win, AG_TOOLBAR_HORIZ, 1, 0);
menu = AG_MenuNew(win, 0);
item = AG_MenuNode(menu->root, "File", NULL);
{
	AG_MenuToolbar(item, toolbar);
	AG_MenuAction(item, "Load", NULL, LoadFile, NULL);
	AG_MenuAction(item, "Save", NULL, SaveFile, NULL);
	AG_MenuToolbar(item, NULL);
}
.Ed
.Pp
The following code fragment creates a menu with an action item, a boolean
item and two bitmask items.
.Bd -literal -offset indent
Uint16 flags = 0;
#define FOO_FLAG 0x01
#define BAR_FLAG 0x02

void
SayHello(AG_Event *event)
{
	char *s = AG_STRING(1);
	AG_TextMsg(AG_MSG_INFO, "Hello, %s!", s);
}

void
QuitApplication(AG_Event *event)
{
	AG_Quit();
}

.Li ...

AG_Menu *menu = AG_MenuNew(win);
AG_MenuItem *item = AG_MenuNode(menu->root, "File", NULL);
{
	AG_MenuInt16Flags(item, "Foo", NULL, &flags, FOO_FLAG, 0);
	AG_MenuInt16Flags(item, "Bar", NULL, &flags, BAR_FLAG, 0);
	AG_MenuAction(item, "Say hello", NULL,
	    SayHello, "%s", "world");
	AG_MenuAction(item, "Quit", NULL,
	    QuitApplication, NULL);
}
.Ed
.Sh SEE ALSO
.Xr AG_Button 3 ,
.Xr AG_Event 3 ,
.Xr AG_Intro 3 ,
.Xr AG_KeySym 3 ,
.Xr AG_Surface 3 ,
.Xr AG_Tlist 3 ,
.Xr AG_Toolbar 3 ,
.Xr AG_Widget 3 ,
.Xr AG_Window 3
.Sh HISTORY
The
.Nm
widget first appeared in Agar 1.0.
